
#ifndef _LEXER_H
#define _LEXER_H

#include <exception>
#include <string>
#include <sstream>
#include <list>

#include "token.hpp"

#define LEX_NUMBER 12

struct LexMatch
{
    enum TokenType type;
    std::string pattern;
};

const std::string WHITESPACE_PATTERN = "[ \f\r\t\v]\\+";

const LexMatch LEXEMES[LEX_NUMBER] = { 
    {END_OF_COMMAND, "\n"}, 
    {IDENTIFIER, "_*[a-zA-Z]\\w*"},   
    {DEF_KEYWORD, "var"}, 
    {FLOAT_NUMBER, "[0-9]*\\.\\?[0-9]\\+\\([eE][-+]\\?[0-9]\\+\\)\\?"}, 
    {INTEGER_NUMBER, "[0-9]\\+"},
    {MUL, "\\*"},
    {PLUS, "+" }, 
    {MINUS, "-"}, 
    {DIV, "/"}, 
    {POW, "\\^"}, 
    {BRACKET_OPEN, "("}, 
    {BRACKET_CLOSE, ")"}, 
};
    
class Lexer {
    public:
        class LexerException {
        public:
            virtual std::string what() const { return "Lexical error"; }
        };
    
        class UnknownLexemeException : public LexerException {
        public:
            UnknownLexemeException(int p) { pos = p; }

            std::string what() const { 
                std::ostringstream oss;
                oss << "Lexical error at position " << pos;
                return oss.str();
            }

            int getPos() { return pos; }
        private:
            int pos;
        };
    
        static TokenStream getTokenStream(const std::string &input = "");
        
    private:
        TokenStream tokens;
};

#endif
